package com.it.xuehang.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.it.xuehang.entity.CityInfo;
import com.it.xuehang.entity.DailyWeatherForecast;
import com.it.xuehang.entity.SyncLog;
import com.it.xuehang.entity.YesterdayWeather;
import com.it.xuehang.mapper.CityInfoMapper;
import com.it.xuehang.mapper.DailyWeatherForecastMapper;
import com.it.xuehang.mapper.SyncLogMapper;
import com.it.xuehang.mapper.YesterdayWeatherMapper;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.it.xuehang.handler.AutoDateConverter.convertToDate;

@Service
public class WeatherSyncService {

    private static final Logger logger = LoggerFactory.getLogger(WeatherSyncService.class);

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private YesterdayWeatherMapper yesterdayWeatherMapper;
    @Autowired
    private SyncLogMapper syncLogMapper;
    @Autowired
    private CityInfoMapper cityInfoMapper;
    @Autowired
    private DailyWeatherForecastMapper dailyWeatherForecastMapper;
    @Value("${weather.api.url}")
    private String url; // 注入配置项


    // 每天凌晨3点执行一次同步任务
    //@Scheduled(cron = "0 0 3 * * ?")
    //5s执行一次
    // @Scheduled(cron = "*/5 * * * * ?")
    //每8h执行一次
//    @Scheduled(cron = "0 0 */8 * * ?")
    @XxlJob("syncWeatherHandler")
    public void syncWeatherData() {
        try {
            Map<String, Object> response = restTemplate.getForObject(url,Map.class);
            logger.info("response:{}", response);

            // 解析城市信息
            Map<String, Object> cityInfo = (Map<String, Object>) response.get("cityInfo");
            logger.info("cityInfo:{}", cityInfo);

            LambdaQueryWrapper<CityInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(CityInfo::getCityId, cityInfo.get("citykey").toString());
            CityInfo dbCity = cityInfoMapper.selectOne(wrapper);
            logger.info("dbCity:{}", dbCity);
            //如果查询不到城市信息，插入
            if(Objects.isNull(dbCity)){
                dbCity = new CityInfo();
                dbCity.setCityId(cityInfo.get("citykey").toString());
                String dateString = (String) response.get("date");
                dbCity.setDate(convertToDate(dateString));
                dbCity.setCity(cityInfo.get("city").toString());
                dbCity.setParentCity(cityInfo.get("parent").toString());
                dbCity.setUpdateTime(cityInfo.get("updateTime").toString());
                cityInfoMapper.insert(dbCity);
                logger.info("插入城市信息成功");
                // 解析昨天的天气数据
                Map<String, Object> data = (Map<String, Object>) response.get("data");
                Map<String, Object> yesterdayData = (Map<String, Object>) data.get("yesterday");
                saveYesterdayWeather(dbCity.getId(), yesterdayData, false);
                // 解析今天的天气预报数据及未来几天的天气预报数据
                List<Map<String, Object>> forecastList = (List<Map<String, Object>>) data.get("forecast");

                for (int i = 0; i < forecastList.size(); i++) {
                    Map<String, Object> dailyForecast = forecastList.get(i);
                    saveDailyWeatherForecast(dbCity.getId(), dailyForecast, data, i, false);
                }
            }else {
                //查询到城市信息，看城市时间是否变化，若变化需要及时更新天气信息
                if(dbCity.getDate().equals(convertToDate((String)response.get("date"))) && dbCity.getUpdateTime().equals(cityInfo.get("updateTime"))){
                    //当天城市信息，事时间没变化，天气信息不需要更新
                    return;
                }else{
                    //当天城市信息，事时间没变化，天气信息需要更新
                    dbCity.setCityId(cityInfo.get("citykey").toString());
                    String dateString = (String) response.get("date");
                    dbCity.setDate(convertToDate(dateString));
                    dbCity.setCity(cityInfo.get("city").toString());
                    dbCity.setParentCity(cityInfo.get("parent").toString());
                    dbCity.setUpdateTime(cityInfo.get("updateTime").toString());
                    cityInfoMapper.updateById(dbCity);
                    // 解析并强制更新昨天的天气数据
                    Map<String, Object> data = (Map<String, Object>) response.get("data");
                    Map<String, Object> yesterdayData = (Map<String, Object>) data.get("yesterday");
                    saveYesterdayWeather(dbCity.getId(), yesterdayData, true); // 强制更新

                    // 解析并强制更新今天的天气预报数据及未来几天的天气预报数据
                    List<Map<String, Object>> forecastList = (List<Map<String, Object>>) data.get("forecast");

                    for (int i = 0; i < forecastList.size(); i++) {
                        Map<String, Object> dailyForecast = forecastList.get(i);
                        saveDailyWeatherForecast(dbCity.getId(), dailyForecast, data, i, true); // 强制更新
                    }
                }

            }

            // 记录同步成功日志
            SyncLog syncLog = new SyncLog();
            syncLog.setStatus("success");
            syncLog.setMessage("Successfully synced weather data for " + dbCity.getCity());
            syncLog.setSyncTime(LocalDateTime.now());
            syncLog.setCityId(dbCity.getId());
            syncLogMapper.insert(syncLog);

            logger.info("Synchronization completed successfully.");

        } catch (Exception e) {
            // 记录同步失败日志
            SyncLog syncLog = new SyncLog();
            syncLog.setStatus("failed");
            syncLog.setMessage("Failed to sync weather data: " + e.getMessage());
            syncLog.setSyncTime(LocalDateTime.now());
            syncLogMapper.insert(syncLog);
            logger.error("Synchronization failed.", e);
        }
    }

    private void saveYesterdayWeather(BigDecimal cityId, Map<String, Object> data, boolean forceUpdate) {
        LocalDate date = LocalDate.parse(data.get("ymd").toString());

        if (!forceUpdate && yesterdayWeatherMapper.existsByCityIdAndDate(cityId, date) > 0) {
            return;
        }

        // 清除旧的数据，保证数据唯一性
        if (forceUpdate) {
            yesterdayWeatherMapper.delete(new LambdaQueryWrapper<YesterdayWeather>()
                    .eq(YesterdayWeather::getCityId, cityId)
                    .eq(YesterdayWeather::getDate, date));
        }

        YesterdayWeather yesterdayWeather = new YesterdayWeather();
        yesterdayWeather.setCityId(cityId);
        yesterdayWeather.setDate(date);
        yesterdayWeather.setWeek(data.get("week").toString());
        yesterdayWeather.setSunrise(data.get("sunrise").toString());
        yesterdayWeather.setHighTemp(new BigDecimal(data.get("high").toString().replace("高温 ", "").replace("℃", "")));
        yesterdayWeather.setLowTemp(new BigDecimal(data.get("low").toString().replace("低温 ", "").replace("℃", "")));
        yesterdayWeather.setSunset(data.get("sunset").toString());
        yesterdayWeather.setAqi(new BigDecimal(data.get("aqi").toString()));
        yesterdayWeather.setWindDirection(data.get("fx").toString());
        yesterdayWeather.setWindStrength(data.get("fl").toString());
        yesterdayWeather.setWeatherType(data.get("type").toString());
        yesterdayWeather.setNotice(data.get("notice").toString());

        yesterdayWeatherMapper.insert(yesterdayWeather);
    }

    private void saveDailyWeatherForecast(BigDecimal cityId, Map<String, Object> data, Map<String, Object> currentData, int dayOffset, boolean forceUpdate) {
        logger.info("Before calculation, dayOffset: {}", dayOffset);
        LocalDate forecastDate = LocalDate.parse(data.get("ymd").toString());
                //.plusDays(dayOffset);
        logger.info("After calculation, dayOffset: {}", dayOffset);
        logger.info("forecastDate: {}", forecastDate);


        if (!forceUpdate && dailyWeatherForecastMapper.existsByCityIdAndForecastDate(cityId, forecastDate) > 0) {
            return;
        }

        // 清除旧的数据，保证数据唯一性
        if (forceUpdate) {
            dailyWeatherForecastMapper.delete(new LambdaQueryWrapper<DailyWeatherForecast>()
                    .eq(DailyWeatherForecast::getCityId, cityId)
                    .eq(DailyWeatherForecast::getForecastDate, forecastDate));
        }

        DailyWeatherForecast forecast = new DailyWeatherForecast();
        forecast.setCityId(cityId);
        forecast.setForecastDate(forecastDate);
        forecast.setWeek(data.get("week").toString());
        forecast.setSunrise(data.get("sunrise").toString());
        forecast.setHighTemp(new BigDecimal(data.get("high").toString().replace("高温 ", "").replace("℃", "")));
        forecast.setLowTemp(new BigDecimal(data.get("low").toString().replace("低温 ", "").replace("℃", "")));
        forecast.setSunset(data.get("sunset").toString());
        forecast.setAqi(new BigDecimal(data.get("aqi").toString()));
        forecast.setWindDirection(data.get("fx").toString());
        forecast.setWindStrength(data.get("fl").toString());
        forecast.setWeatherType(data.get("type").toString());
        forecast.setNotice(data.get("notice").toString());
        forecast.setSystemUpdateTime(LocalDateTime.now()); // 系统更新时间

        // Additional fields from 'currentData' object
        forecast.setHumidity(currentData.get("shidu").toString());
        forecast.setPm25(new BigDecimal(currentData.get("pm25").toString()));
        forecast.setPm10(new BigDecimal(currentData.get("pm10").toString()));
        forecast.setAirQuality(currentData.get("quality").toString());
        forecast.setTemperature(currentData.get("wendu").toString());
        forecast.setColdIndex(currentData.get("ganmao").toString());

        dailyWeatherForecastMapper.insert(forecast);
    }
}